"""
消息处理模块
包含消息解析、AI调用、消息发送等功能
"""

import logging
import threading
import xml.etree.ElementTree as ET
from services.llm import call_llm_gemini_image
from handlers.ai_response_strategy import AIResponseStrategy
from handlers.conversation_manager import ConversationManager

logger = logging.getLogger(__name__)


class MessageHandler:
    """消息处理器"""
    
    def __init__(self, wx_api, wx_crypto):
        """
        初始化消息处理器
        
        Args:
            wx_api: 企业微信API实例
            wx_crypto: 企业微信加密服务实例
        """
        self.wx_api = wx_api
        self.wx_crypto = wx_crypto
        
        # 消息去重缓存（避免处理重复消息）
        self.processed_messages = set()
        self.max_cache_size = 1000
        
        # 初始化对话管理器和AI回复策略
        self.conversation_manager = ConversationManager()
        self.ai_response_strategy = AIResponseStrategy(self.conversation_manager)
    
    def parse_xml_message(self, xml_content):
        """
        解析XML格式的企业微信消息，兼容自建应用和客服格式
        
        Args:
            xml_content: XML格式的消息内容
            
        Returns:
            dict: 解析后的消息字典
        """
        try:
            # 优先使用模块化消息解析器
            if self.wx_crypto:
                parsed = self.wx_crypto.parse_xml_message(xml_content)
                if parsed:
                    return parsed
            
            # 如果模块化解析失败，使用兼容性解析
            root = ET.fromstring(xml_content)
            msg_type = root.find('MsgType').text

            # 兼容字段不存在的情况
            def get_text(node, tag):
                n = node.find(tag)
                return n.text if n is not None else ""

            from_user = get_text(root, 'FromUserName')
            to_user = get_text(root, 'ToUserName')
            create_time = get_text(root, 'CreateTime')
            msg_id = get_text(root, 'MsgId')

            content = ""
            if msg_type == 'text':
                # 企业微信客服消息格式：<Text><Content>
                text_node = root.find('Text')
                if text_node is not None and text_node.find('Content') is not None:
                    content = text_node.find('Content').text
                else:
                    # 兼容自建应用格式：<Content>
                    content_node = root.find('Content')
                    if content_node is not None:
                        content = content_node.text
            elif msg_type == 'image':
                image_node = root.find('Image')
                if image_node is not None and image_node.find('MediaId') is not None:
                    content = f"[图片消息] {image_node.find('MediaId').text}"
                else:
                    pic_url = get_text(root, 'PicUrl')
                    media_id = get_text(root, 'MediaId')
                    content = f"[图片消息] {pic_url or media_id}"
            elif msg_type == 'voice':
                voice_node = root.find('Voice')
                if voice_node is not None and voice_node.find('MediaId') is not None:
                    content = f"[语音消息] {voice_node.find('MediaId').text}"
                else:
                    media_id = get_text(root, 'MediaId')
                    format_type = get_text(root, 'Format')
                    content = f"[语音消息] 格式: {format_type}"
            elif msg_type == 'video':
                video_node = root.find('Video')
                if video_node is not None and video_node.find('MediaId') is not None:
                    content = f"[视频消息] {video_node.find('MediaId').text}"
                else:
                    media_id = get_text(root, 'MediaId')
                    thumb_media_id = get_text(root, 'ThumbMediaId')
                    content = f"[视频消息]"
            elif msg_type == 'location':
                location_x = get_text(root, 'Location_X')
                location_y = get_text(root, 'Location_Y')
                scale = get_text(root, 'Scale')
                label = get_text(root, 'Label')
                content = f"[位置消息] {label} ({location_x}, {location_y})"
            elif msg_type == 'link':
                title = get_text(root, 'Title')
                description = get_text(root, 'Description')
                url = get_text(root, 'Url')
                content = f"[链接消息] {title}: {description}"
            elif msg_type == 'event':
                event = get_text(root, 'Event')
                content = f"[事件消息] {event}"
            else:
                content = f"[{msg_type}类型消息]"

            return {
                'msg_type': msg_type,
                'from_user': from_user,
                'to_user': to_user,
                'create_time': create_time,
                'msg_id': msg_id,
                'content': content,
                'raw_xml': xml_content
            }
        except Exception as e:
            logger.error(f"解析XML消息失败: {str(e)}")
            return None

    def call_ai_api(self, message, customer_id=None):
        """
        调用AI API进行智能回复
        
        Args:
            message: 用户消息
            customer_id: 客户ID（可选）
            
        Returns:
            str: AI回复内容
        """
        logger.info(f"call_ai_api被调用，message: '{message}', customer_id: '{customer_id}', customer_id类型: {type(customer_id)}")
        
        try:
            # 使用 prompts.py 的提示词生成逻辑
            from config.prompts import PromptConfig
            conv_id = customer_id if customer_id else "anonymous"
            conversation_history = self.conversation_manager.get_relevant_history(conv_id)
            prompt = PromptConfig.generate_prompt(
                current_message=message,
                conversation_history=conversation_history,
                task_type=None
            )
            response = call_llm_gemini_image(prompt, {}, return_json=True)
            # response 类型
            logger.info(f"response 类型: {type(response)}")
            logger.info(f"AI回复: {response}")
            import json, re
            response_data = None
            try:
                if isinstance(response, str):
                    clean_response = re.sub(r'^```(json)?\s*\n', '', response)
                    clean_response = re.sub(r'\n```\s*$', '', clean_response)
                    response_data = json.loads(clean_response)
                else:
                    response_data = response
            except Exception as e:
                logger.error(f"解析AI回复JSON失败: {str(e)}，直接返回原始回复")
                return response if isinstance(response, str) else str(response)

            ai_task_type = response_data.get("当前任务")
            logger.info(f"AI解析出的当前任务: {ai_task_type}")
            ai_reply = response_data.get("AI客服回复", "抱歉，处理您的消息时出现了问题。")
            logger.info(f"最终返回AI客服回复: {ai_reply}")

            # 始终调用 ai_response_strategy.process_message，让其根据 response_data 决定分支
            if customer_id:
                logger.info(f"使用AI回复策略，客户ID: {customer_id}")
                result = self.ai_response_strategy.process_message(customer_id, message, response_data)
                
                # 检查是否需要转人工
                need_human = result.get("need_human", False)
                if need_human:
                    logger.info("🎯 AI策略决定转人工客服")
                    # 这里可以触发转人工逻辑，但先返回AI的回复
                    ai_reply = result.get("ai_response", ai_reply)
                else:
                    logger.info("🎯 AI策略决定AI直接回复")
                    ai_reply = result.get("ai_response", ai_reply)
                
                logger.info(f"=== call_ai_api方法结束（新策略）===")
                return ai_reply
            else:
                logger.info("customer_id为空，也走AI回复策略")
                result = self.ai_response_strategy.process_message("anonymous", message, response_data)
                
                # 检查是否需要转人工
                need_human = result.get("need_human", False)
                if need_human:
                    logger.info("🎯 AI策略决定转人工客服（匿名用户）")
                    ai_reply = result.get("ai_response", ai_reply)
                else:
                    logger.info("🎯 AI策略决定AI直接回复（匿名用户）")
                    ai_reply = result.get("ai_response", ai_reply)
                
                logger.info(f"最终返回AI客服回复: {ai_reply}")
                logger.info(f"=== call_ai_api方法结束（无ID策略）===")
                return ai_reply
        except Exception as e:
            logger.error(f"❌ 调用AI API失败: {str(e)}")
            logger.info(f"=== call_ai_api方法结束（异常）===")
            return "抱歉，AI服务暂时不可用，请稍后再试。"

    def process_kf_message_async(self, wx_api, config):
        """
        异步处理客服消息
        
        Args:
            wx_api: 企业微信API实例
            config: 配置对象
        """
        def process_async():
            try:
                # 获取客服消息
                logger.info(f"开始调用 get_kf_messages，wx_api类型: {type(wx_api)}")
                logger.info(f"wx_api方法: {dir(wx_api)}")
                messages_result = wx_api.get_kf_messages()
                if not messages_result:
                    logger.error("获取客服消息失败，可能是IP白名单问题")
                    return
                
                # 打印完整的消息结果用于调试
                # import json
                # logger.info(f"获取到的客服消息结果: {json.dumps(messages_result, ensure_ascii=False, indent=2)}")
                
                # 处理获取到的消息
                msg_list = messages_result.get('msg_list', [])
                if not msg_list:
                    logger.info("没有新的客服消息")
                    return
                
                # 找到最后一条文本消息
                latest_text_msg = None
                for msg in reversed(msg_list):  # 从最新的开始查找
                    if msg.get('msgtype') == 'text':
                        latest_text_msg = msg
                        break
                
                if not latest_text_msg:
                    logger.info("没有找到文本消息")
                    return
                
                # 检查消息是否已处理过
                msg_id = latest_text_msg.get('msgid', '')
                send_time = latest_text_msg.get('send_time', '')
                unique_msg_id = f"{send_time}_{msg_id}"
                
                if unique_msg_id and unique_msg_id in self.processed_messages:
                    logger.info(f"客服消息已处理过，跳过: {unique_msg_id}")
                    return
                
                # 处理最后一条文本消息
                msg_type_kf = latest_text_msg.get('msgtype', '')
                external_userid = latest_text_msg.get('external_userid', '')
                open_kfid = latest_text_msg.get('open_kfid', '')
                text_content = latest_text_msg.get('text', {}).get('content', '')
                
                logger.info(f"处理最后一条文本消息: 类型={msg_type_kf}, 用户={external_userid}, 内容={text_content}")
                logger.info(f"external_userid类型: {type(external_userid)}, 值: '{external_userid}'")
                
                if text_content:
                    logger.info(f"用户消息: {text_content}")
                    logger.info(f"准备调用call_ai_api，参数: text_content='{text_content}', external_userid='{external_userid}'")
                    
                    # 调用AI API
                    ai_response = self.call_ai_api(text_content, external_userid)
                    logger.info(f"AI回复: {ai_response}")
                    
                    # 检查当前是否在人工服务状态
                    is_human_service = self.conversation_manager.is_currently_human_service(external_userid)
                    if is_human_service:
                        # 在人工服务状态下，更新沟通时间
                        self.conversation_manager.update_communication_time(external_userid)
                        logger.info(f"💬 客户 {external_userid} 在人工服务状态，已更新沟通时间")
                    
                    # 记录任务类型用于日志
                    if ai_response:
                        # 简单的任务类型判断
                        if any(keyword in ai_response for keyword in ['下单', '商品', '价格', '颜色', '数量', '收货人', '地址', '电话']):
                            logger.info("📦 检测到下单/查询任务")
                        else:
                            logger.info("💬 检测到一般对话任务")
                    
                    # 发送客服回复
                    if wx_api.send_kf_message(open_kfid, external_userid, 'text', ai_response):
                        # 标记消息已处理
                        if unique_msg_id:
                            self.processed_messages.add(unique_msg_id)
                        logger.info(f"已处理用户消息'{text_content}'并回复")
                    else:
                        logger.error("AI回复已生成，但发送失败")
                        # 进行状态诊断
                        try:
                            session_status = wx_api.check_session_status(open_kfid, external_userid)
                            if session_status:
                                logger.info(f"会话状态检查结果: {session_status}")
                                if session_status.get('service_state') != 1:
                                    logger.warning("会话状态不正确，可能需要重新建立会话")
                            else:
                                logger.error("无法检查会话状态")
                        except Exception as e:
                            logger.error(f"检查会话状态时发生错误: {str(e)}")
                else:
                    logger.info("收到文本消息，但内容为空")
            except Exception as e:
                logger.error(f"异步处理客服消息时发生错误: {str(e)}")
        
        thread = threading.Thread(target=process_async)
        thread.daemon = True
        thread.start()
        logger.info("客服消息处理已启动异步线程")

    def process_message(self, message_data, webhook_url=None):
        """
        处理接收到的消息
        
        Args:
            message_data: 消息数据
            webhook_url: webhook地址，如果为None则使用默认配置
        """
        logger.info(f"处理消息: {message_data}")
        try:
            # 检查消息是否已处理过（去重）
            msg_id = message_data.get('msg_id', '')
            if msg_id in self.processed_messages:
                logger.info(f"消息 {msg_id} 已处理过，跳过")
                return
            
            # 添加到已处理集合
            self.processed_messages.add(msg_id)
            if len(self.processed_messages) > self.max_cache_size:
                # 清理旧消息
                self.processed_messages.clear()
            
            # 获取消息内容
            content = message_data.get('content', '')
            if not content:
                logger.warning("消息内容为空，跳过处理")
                return
            
            # 调用AI API获取回复
            ai_response = self.call_ai_api(content)
            
            # 发送回复
            if ai_response:
                if webhook_url:
                    self.wx_api.send_webhook_message(webhook_url, ai_response)
                else:
                    logger.warning("未配置webhook_url，无法发送回复")
            
        except Exception as e:
            logger.error(f"处理消息时发生错误: {str(e)}")

    def process_message_async(self, message_data, webhook_url=None):
        """
        异步处理消息
        
        Args:
            message_data: 消息数据
            webhook_url: webhook地址
        """
        def process_async():
            self.process_message(message_data, webhook_url)
        
        thread = threading.Thread(target=process_async)
        thread.daemon = True
        thread.start()
        logger.info("消息处理已启动异步线程")

    def verify_signature(self, timestamp, nonce, signature, body, secret):
        """
        验证企业微信签名
        
        Args:
            timestamp: 时间戳
            nonce: 随机字符串
            signature: 签名
            body: 请求体
            secret: 签名密钥
            
        Returns:
            bool: 签名是否有效
        """
        import hashlib
        import hmac
        import base64
        
        if not secret:
            return True  # 如果没有设置密钥，跳过验证
            
        # 构造签名字符串
        string_to_sign = f"{timestamp}\n{nonce}\n{body}\n"
        
        # 使用HMAC-SHA256计算签名
        hmac_obj = hmac.new(
            secret.encode('utf-8'),
            string_to_sign.encode('utf-8'),
            hashlib.sha256
        )
        expected_signature = base64.b64encode(hmac_obj.digest()).decode('utf-8')
        
        return hmac.compare_digest(signature, expected_signature) 